#include <iostream>
#include <complex>
#include <cstring>
#include "qpsk_mod.hpp"
using namespace std;

// @ define grey code format
const char *grey_code[4] = {"00", "01", "11", "10"};

// * QPSK modulation
// * param:char* bytes
// * param:size :QPSK modulation point
// * param:complex<double>* result
// * two char serial-to-parallel conversion
// * grey QPSK
// ! remind to release memory in the main function
complex<double> *modulation(char *bytes, int size)
{
    complex<double> *result = new complex<double>[size];         // allocate memory for result
    int index = 0;                                               // pointer
    for (size_t i = 0; bytes[i] != '\0' && i < size * 2; i += 2) // two char
    {
        string current = "";
        if (bytes[i + 1] != '\0')
        {
            current.push_back(bytes[i]);
            current.push_back(bytes[i + 1]);
        }
        else
        {
            current.push_back(bytes[i]);
            current.push_back('0'); // add 0 if size is odd
        }

        if (strcmp(current.c_str(), grey_code[0]) == 0) // accrding to grey code mapping into signal space
        {
            result[index++] = complex<double>(sqrt(2) / 2, sqrt(2) / 2);
            // cout << current << " " << complex<double>(sqrt(2) / 2, sqrt(2) / 2) << endl;
        }
        else if (strcmp(current.c_str(), grey_code[1]) == 0)
        {
            result[index++] = complex<double>(sqrt(2) / 2, -sqrt(2) / 2);
            // cout << current << " " << complex<double>(-sqrt(2) / 2, sqrt(2) / 2) << endl;
        }
        else if (strcmp(current.c_str(), grey_code[2]) == 0)
        {
            result[index++] = complex<double>(-sqrt(2) / 2, -sqrt(2) / 2);
            // cout << current << " " << complex<double>(-sqrt(2) / 2, -sqrt(2) / 2) << endl;
        }
        else if (strcmp(current.c_str(), grey_code[3]) == 0)
        {
            result[index++] = complex<double>(sqrt(2) / 2, -sqrt(2) / 2);
            // cout << current << " " << complex<double>(sqrt(2) / 2, -sqrt(2) / 2) << endl;
        }
    }
    for (; index < size;)
    {
        result[index++] = complex<double>(sqrt(2) / 2, sqrt(2) / 2);
        // cout << "add 00"
        //      << " " << complex<double>(sqrt(2) / 2, sqrt(2) / 2) << endl;
    }
    return result; // return complex<double> pointer
}